package com.todo.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/**
 * 手机号加密工具类
 * 使用AES加密算法对敏感的手机号信息进行加密存储和解密查询
 * 
 * 加密流程：手机号 -> AES加密 -> Base64编码 -> 存储到数据库
 * 解密流程：数据库读取 -> Base64解码 -> AES解密 -> 原始手机号
 */
@Slf4j
@Component
@SuppressWarnings("all")
public class PhoneEncryptUtil {

    /**
     * AES加密算法名称
     */
    private static final String ALGORITHM = "AES";
    
    /**
     * AES加密模式和填充方式
     */
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";

    /**
     * 从配置文件读取加密密钥
     * 在生产环境中，应该使用环境变量或专门的密钥管理系统
     */
    @Value("${phone.encrypt.key:TodoPhoneEncryptKey2024@#$%}")
    private String encryptKey;

    /**
     * 加密手机号
     * @param phone 原始手机号
     * @return 加密后的Base64字符串
     */
    public String encrypt(String phone) {
        if (phone == null || phone.trim().isEmpty()) {
            return null;
        }

        try {
            // 处理密钥，确保长度为32字节（256位）
            byte[] keyBytes = getFixedLengthKey(encryptKey);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);

            // 创建加密器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);

            // 执行加密
            byte[] encryptedBytes = cipher.doFinal(phone.getBytes(StandardCharsets.UTF_8));

            // 使用Base64编码返回
            String encryptedPhone = Base64.getEncoder().encodeToString(encryptedBytes);
            
            log.debug("手机号加密成功，原始长度: {}, 加密后长度: {}", phone.length(), encryptedPhone.length());
            return encryptedPhone;

        } catch (Exception e) {
            log.error("手机号加密失败: {}", phone, e);
            throw new RuntimeException("手机号加密失败", e);
        }
    }

    /**
     * 解密手机号
     * @param encryptedPhone 加密后的Base64字符串
     * @return 原始手机号
     */
    public String decrypt(String encryptedPhone) {
        if (encryptedPhone == null || encryptedPhone.trim().isEmpty()) {
            return null;
        }

        try {
            // 处理密钥，确保长度为32字节（256位）
            byte[] keyBytes = getFixedLengthKey(encryptKey);
            SecretKeySpec secretKey = new SecretKeySpec(keyBytes, ALGORITHM);

            // 创建解密器
            Cipher cipher = Cipher.getInstance(TRANSFORMATION);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);

            // Base64解码
            byte[] encryptedBytes = Base64.getDecoder().decode(encryptedPhone);

            // 执行解密
            byte[] decryptedBytes = cipher.doFinal(encryptedBytes);

            // 转换为字符串
            String originalPhone = new String(decryptedBytes, StandardCharsets.UTF_8);
            
            log.debug("手机号解密成功，解密后长度: {}", originalPhone.length());
            return originalPhone;

        } catch (Exception e) {
            log.error("手机号解密失败: {}", encryptedPhone, e);
            throw new RuntimeException("手机号解密失败", e);
        }
    }

    /**
     * 验证手机号是否匹配（用于登录验证）
     * @param plainPhone 明文手机号
     * @param encryptedPhone 加密后的手机号
     * @return 是否匹配
     */
    public boolean matches(String plainPhone, String encryptedPhone) {
        if (plainPhone == null || encryptedPhone == null) {
            return false;
        }

        try {
            String decryptedPhone = decrypt(encryptedPhone);
            return plainPhone.equals(decryptedPhone);
        } catch (Exception e) {
            log.error("手机号匹配验证失败: plainPhone={}, encryptedPhone={}", plainPhone, encryptedPhone, e);
            return false;
        }
    }

    /**
     * 生成用于测试的随机密钥（仅用于开发测试）
     * 在生产环境中应使用固定的、安全管理的密钥
     * @return Base64编码的密钥
     */
    public static String generateRandomKey() {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
            keyGenerator.init(256, new SecureRandom());
            SecretKey secretKey = keyGenerator.generateKey();
            return Base64.getEncoder().encodeToString(secretKey.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException("生成密钥失败", e);
        }
    }

    /**
     * 处理密钥，确保长度为32字节（256位AES）
     * @param originalKey 原始密钥字符串
     * @return 固定长度的密钥字节数组
     */
    private byte[] getFixedLengthKey(String originalKey) {
        byte[] keyBytes = new byte[32]; // 256位 = 32字节
        
        if (originalKey != null) {
            byte[] originalBytes = originalKey.getBytes(StandardCharsets.UTF_8);
            
            // 如果原始密钥长度小于32字节，则用0填充
            // 如果原始密钥长度大于32字节，则截取前32字节
            System.arraycopy(originalBytes, 0, keyBytes, 0, 
                Math.min(originalBytes.length, keyBytes.length));
        }
        
        return keyBytes;
    }

    /**
     * 脱敏显示手机号（用于日志记录和前端显示）
     * 例如：13800138000 -> 138****8000
     * @param phone 原始手机号
     * @return 脱敏后的手机号
     */
    public static String maskPhone(String phone) {
        if (phone == null || phone.length() != 11) {
            return "***";
        }
        return phone.substring(0, 3) + "****" + phone.substring(7);
    }
} 